home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / boi120p.zip / UNITS.ZIP / GETCMBBS.PAS < prev    next >
Pascal/Delphi Source File  |  1990-12-11  |  49KB  |  1,025 lines

  1. {$D-}  { Disable Debug Information }
  2. {$S-}  { Disable Stack Checking }
  3. {$V-}  { Disable String Checking }
  4.  
  5. Unit GetCmBBS;
  6. { Part of BBS Onliner Interface }
  7. { Copyright (C) 1990 Andrew J. Mead
  8.   All Rights Reserved. }
  9.  
  10. { Original version 7/1/90 }
  11. { Original release version 9/5/90 }
  12. { Original public release 12/15/90 }
  13. { history found in IOLIB.PAS }
  14.  
  15.  
  16. INTERFACE
  17.  
  18. Uses
  19.   boidecl,
  20.   DOS;
  21.  
  22. Procedure GETCOMMAND(       { process command line parameters }
  23.     infofile,               { name of documentation file }
  24.     inhof,                  { default name for text hall of fame }
  25.     logfile    : pathstr;   { name of error log }
  26.     gamename,               { name of current game }
  27.     version    : string;    { version of current game }
  28.     programset : charset);  { set of program's command line switches }
  29.  
  30. IMPLEMENTATION
  31.  
  32. Uses
  33.   iolib;
  34.  
  35. Type
  36.   IRQtype   = array [0..15] of byte;   { array of IRQ information }
  37.   portype   = array [0..3] of word;    { default port addressess  }
  38.  
  39. Var
  40.   inchar    : char;                    { standard input character }
  41.   minmax    : byte;                    { maximum time allowed }
  42.  
  43. Const
  44.   timedone  : boolean = false; { remaining time figured }
  45.   filedone  : boolean = false; { BBS file processed }
  46.   hofdone   : boolean = false; { /y processed }
  47.   lockcomm  : boolean = false; { /c processed }
  48.   lockIRQ   : boolean = false; { /i processed }
  49.   locklocal : boolean = false; { /l processed }
  50.   lockname  : boolean = false; { /n processed }
  51.   setlocal  : boolean = false; { BBS file says it is in local play }
  52.   portarray : portype =        { default port addressess for Com1 - Com4 }
  53.       ($3F8,$2F8,$3E8,$2E8);
  54.   IRQarray  : IRQtype =        { interrupt vectors for IRQs 0 - 15 }
  55.       ($08,$09,$0A,$0B,$0C,$0D,$0E,$0F,$70,$71,$72,$73,$74,$75,$76,$77);
  56.   Initarray : IRQtype =        { 8259A IRQ enabling masks-used in Async.Pas }
  57.       ($FE,$FD,$FB,$F7,$EF,$DF,$BF,$7F,$FB,$FB,$FB,$FB,$FB,$FB,$FB,$FB);
  58.       { Entries 8-15 are unknown the cascade mask (for IRQ2) is used }
  59.  
  60.   IRQnum    : byte    = 4;     { default IRQ - Com1 Com3 }
  61.  
  62. Procedure GETCOMMAND;
  63.   var
  64.     gcf         : text;        { user information text file handle }
  65.     gcb         : file;        { user information byte file handle }
  66.     gbuffer     : array [1..4096] of char; { buffer for gcf-text file buffer }
  67.     gcbuffer    : array [0..4095] of byte; { buffer for gcb-binary file buffer}
  68.     gcstr       : string;      { current input line from gcf }
  69.     insize      : word;        { size of gcb }
  70.     dummy       : word;        { Val conversion error value }
  71.     timetemp    : real;        { Second/Minute time conversion variable }
  72.     opchs       : string [2];  { Opus-CBCS Task Designation }
  73.     gloop       : byte;
  74.  
  75.   Procedure SHOWERROR(param : byte;passtr : string);
  76.   { display error in command line arguments }
  77.     var s : text;              { errorlog file handle }
  78.  
  79.     Procedure WRITEERROR(outstr : string);
  80.       begin {* GetCommand,ShowError,WriteError *}
  81.         write(s,'Abnormal termination of program at');
  82.         GetTime(hour,minute,second,hunsec);
  83. {time}  write(s,hour:1,':',minute:1,':',second:1,'  ');
  84.         GetDate(hour,minute,second,hunsec);
  85. {date}  writeln(s,minute:1,'/',second:1,'/',hour:1,'.');
  86.         writeln(s,'ERROR ',param:0);
  87.         writeln(outstr);
  88.         writeln(s,outstr);
  89.         writeln(s)
  90.       end;  {* GetCommand,ShowError,WriteError *}
  91.  
  92.     begin  {* GetCommand,ShowError *}
  93.       write(#27'[2J');
  94.       assign(s,logfile);
  95.       if exist(logfile) then append(s) else rewrite(s);
  96.       writeln(gamename,' version ',version,'.');
  97.       writeln('Copyright (C) 1990 Andrew J. Mead');
  98.       writeln('All Rights Reserved.');
  99.       writeln('Contact: POB 1155 Chapel Hill, NC 27514-1155');
  100.       writeln;
  101.       writeln('Abnormal termination of program:');
  102.       writeln;
  103.       writeln('ERROR ',param:0);
  104.       case param of
  105.            1 : WriteError('Too many command line arguments.');
  106.            2 : WriteError('Unknown or incorrect argument on command line.');
  107.            3 : WriteError(passtr+' file format not supported yet.');
  108.            4 : WriteError('Unable to find '+passtr+'.  Check implementation or notify Sysop.');
  109.            5 : WriteError('Error in '+passtr+'.  Check implementation.');
  110.            7 : WriteError('Duplicate directives.');
  111.            8 : WriteError('Path/Filename for Hall of Fame is not valid.');
  112.            9 : WriteError(passtr+' is not a valid path.');
  113.           10 : WriteError('Invalid port setting(s) in '+passtr+'.');
  114.           11 : WriteError('Invalid or missing numeric in /X:nn.');
  115.           12 : WriteError('Hall of Fame limit out of range, must be in 1-19.');
  116.           13 : WriteError('Invalid or missing value in /C:n.  ''n'' should be 1-4');
  117.           16 : WriteError('/L can not be used with either /C or /I');
  118.           17 : WriteError('Invalid format in /I:i:nnnn.');
  119.           18 : WriteError(passtr+' is not a valid Hexadecimal address in /I statement.');
  120.           19 : WriteError('Invalid numeric in /A:x.');
  121.           20 : WriteError('/A timeleft should be at least 5.');
  122.           21 : WriteError('Error reading data file, check documentation for proper switch.')
  123.         end;
  124.       writeln;
  125.       writeln('Check ',infofile,' for proper installation of this program.');
  126.       writeln('Report error message to SysOp.');
  127.       writeln;
  128.       writeln('Error saved in ',logfile,'.');
  129.       delay(5000);
  130.       writeln('Now returning to BBS.');
  131.       close(s);
  132.       halt
  133.     end;  {* GetCommand,ShowError *}
  134.  
  135.   Procedure PROCESSTEXT(      { process BBS system text file for user info }
  136.       filestr   : pathstr;    { name of BBS system file }
  137.       getname,                { username is in file indicator }
  138.       getime,                 { user time remaining is in file indicator }
  139.       getlines,               { user screen length is in file indicator }
  140.       ismins    : boolean;    { user time remaining is in minutes indicator }
  141.       nameline,               { line at which users name is found }
  142.       timeline,               { line at which users time remaining is found }
  143.       lineline,               { line at which users screen length is found }
  144.       comline,                { line at which the comport is listed }
  145.       combyte,                { byte in comline that determines comport }
  146.       doextra   : byte);      { extra information for a given file - switch }
  147.  
  148.     Procedure RESTART(readline : byte);
  149.     { places the given lines information in gcstring }
  150.       var rloop : byte;
  151.  
  152.       begin {* GetCommand,ProcessText,Restart *}
  153.         reset(gcf);
  154.         {$I-}
  155.         for rloop := 1 to readline do readln(gcf,gcstr);
  156.         {$I+}
  157.         if IOResult <> 0 then ShowError(5,filestr)
  158.       end;  {* GetCommand,ProcessText,Restart *}
  159.  
  160.     Procedure DORBBS;
  161.     { get users last name, and append it to the first name }
  162.       begin {* GetCommand,ProcessText,DoRBBS *}
  163.         Restart(8); { Get user's last name }
  164.         username := username + ' ' + gcstr
  165.       end;  {* GetCommand,ProcessText,DoRBBS *}
  166.  
  167.     Procedure DOWWIV;
  168.     { check to see if game is being played locally or from remote }
  169.     { get user's real name }
  170.       begin {* GetCommand,ProcessText,DoWWIV *}
  171.         Restart(15);
  172.         while (gcstr[1] = ' ') and (length(gcstr) > 0) do delete(gcstr,1,1);
  173.         if (length(gcstr) > 0) and (gcstr[1] = '0') then setlocal := true;
  174.         Restart(3);
  175.         usereal := true;
  176.         realname := gcstr;
  177.         Restart(1);
  178.         realname := '#'+ gcstr + ' ' + realname
  179.       end;  {* GetCommand,ProcessText,DoWWIV *}
  180.  
  181.     Procedure DOSPITFIRE;
  182.     { get user's user number }
  183.       begin {* GetCommand,ProcessText,DoSpitfire *}
  184.         Restart(1);
  185.         usereal := true;
  186.         realname := '#' + gcstr
  187.       end;  {* GetCommand,ProcessText,DoSpitfire *}
  188.  
  189.     Procedure DOWILDCAT;
  190.     { check to see if game is being played locally or from remote }
  191.       begin {* GetCommand,ProcessText,DoWildCat *}
  192.         Restart(28);
  193.         if Pos('LOCAL',gcstr) > 0 then setlocal := true
  194.       end;  {* GetCommand,ProcessText,DoWildCat *}
  195.  
  196.     Procedure DO2AM;
  197.       begin {* GetCommand,ProcessText,Do2AM *}
  198.         Restart(6); { Get user's last name }
  199.         username := username + ' ' + gcstr;
  200.         Restart(3);
  201.         usereal := true;
  202.         realname := gcstr
  203.       end;  {* GetCommand,ProcessText,Do2AM *}
  204.  
  205.     Procedure DOPHOENIX;
  206.       begin {* GetCommand,ProcessText,DoPhoenix *}
  207.         Restart(2);
  208.         if Pos('LOCAL',gcstr) > 0 then setlocal := true
  209.       end;  {* GetCommand,ProcessText,DoPhoenix *}
  210.  
  211.     begin {* GetCommand,ProcessText *}
  212.       if filedone then ShowError(7,'') else filedone := true;
  213.       if length(gcstr) > 2 then
  214.         begin
  215.           delete(gcstr,1,2);
  216.           if gcstr[1] = ':' then delete(gcstr,1,1);
  217.           if not (gcstr[length(gcstr)] in [':','\']) then gcstr := gcstr + '\';
  218.           filestr := gcstr + filestr;
  219.           if not Valid(filestr) then ShowError(9,gcstr)
  220.         end;
  221.       if not Exist(filestr) then ShowError(4,filestr);
  222.       assign(gcf,filestr);
  223.       SetTextBuf(gcf,gbuffer);
  224.       if getname then              { get users name }
  225.         begin
  226.           Restart(nameline);
  227.           usename := true;
  228.           username := copy(gcstr,1,39)
  229.         end
  230.       else usename := false;
  231.       if getime then               { get users time remaining }
  232.         begin
  233.           Restart(timeline);
  234.           while (gcstr[1] = ' ') and (length(gcstr) > 0) do Delete(gcstr,1,1);
  235.           while (gcstr[length(gcstr)] = ' ') and (length(gcstr) > 0) do Delete(gcstr,length(gcstr),1);
  236.           Val(gcstr,timetemp,dummy);
  237.           if dummy <> 0 then ShowError(5,filestr);
  238.           if ismins then timeleft := trunc(timetemp) else timeleft := trunc(timetemp/60.0);
  239.           if timeleft < 10 then timeleft := 8 else Dec(timeleft,2);
  240.           usetime := true;
  241.           if timedone then timeleft := Min(timeleft,minmax - 2);
  242.           timeleft := Min(timeleft,50);
  243.           GetTime(hour,minute,second,hunsec)
  244.         end
  245.       else usetime := false;
  246.       if getlines then             { get users screen size }
  247.         begin
  248.           Restart(lineline);
  249.           while (gcstr[1] = ' ') and (length(gcstr) > 0) do Delete(gcstr,1,1);
  250.           while (gcstr[length(gcstr)] = ' ') and (length(gcstr) > 0) do Delete(gcstr,length(gcstr),1);
  251.           Val(gcstr,pagelength,dummy);
  252.           if dummy <> 0 then ShowError(5,filestr);
  253.           if pagelength > 24 then Dec(pagelength)
  254.         end;
  255.       if not (lockcomm or locklocal or lockIRQ) then
  256.         begin                      { get communications port }
  257.           Restart(comline);
  258.           case gcstr[combyte] of
  259.               '0' : setlocal := true;
  260.               '1'..'4' :
  261.                 begin
  262.                   dolocal := false;
  263.                   if gcstr[combyte] in ['2','4'] then IRQnum := 3;
  264.                   portnum := ord(gcstr[combyte]) - ord('1')
  265.                 end
  266.             end
  267.         end;
  268.       case doextra of
  269.           1 : DoRBBS;
  270.           2 : DoWWIV;
  271.           3 : DoWildCat;
  272.           4 : Do2AM;
  273.           5 : DoPhoenix;
  274.           6 : DoSpitfire
  275.         end;
  276.       close(gcf)
  277.     end;  {* GetCommand,ProcessText *}
  278.  
  279.   Procedure PROCESSFILE(      { process BBS system data file for user info }
  280.       filestr   : pathstr;    { name of BBS system file }
  281.       getname,                { username is in file indicator }
  282.       getime,                 { user time remaining is in file indicator }
  283.       getlines,               { user screen length is in file indicatior }
  284.       ismins    : boolean;    { user time remaining is in minutes indicator }
  285.       nameoff   : word;       { username offset }
  286.       namesize  : byte;       { username string size }
  287.       timeoff,                { user time offset }
  288.       lineoff,                { user screen length offset }
  289.       commoff,                { communication port offset }
  290.       localkey  : word;       { local mode indicator value }
  291.       doextra   : byte);      { extra processing switch }
  292.  
  293.     Procedure DOOPUS114;
  294.     { get user's real name }
  295.       begin {* GetCommand,ProcessFile,DoOpus114 *}
  296.         move(gcbuffer[0],realname[1],36);
  297.         realname[0] := chr(36);
  298.         if Pos(#0,realname) > 0 then realname[0] := chr(Pos(#0,realname) - 1)
  299.         else while realname[length(realname)] = ' ' do Dec(realname[0]);
  300.         if length(realname) > 0 then
  301.             if (length(username) = 0) then username := realname else usereal := true
  302.       end;  {* GetCommand,ProcessFile,DoOpus114 *}
  303.  
  304.     begin {* GetCommand,ProcessFile *}
  305.       if filedone then ShowError(7,'') else filedone := true;
  306.       if length(gcstr) > 2 then
  307.         begin
  308.           delete(gcstr,1,2);
  309.           if gcstr[1] = ':' then delete(gcstr,1,1);
  310.           if not (gcstr[length(gcstr)] in [':','\']) then gcstr := gcstr + '\';
  311.           filestr := gcstr + filestr;
  312.           if not Valid(filestr) then ShowError(9,gcstr)
  313.         end;
  314.       if not Exist(filestr) then ShowError(4,filestr);
  315.       assign(gcb,filestr);
  316.       reset(gcb,1);
  317.       blockread(gcb,gcbuffer,filesize(gcb),insize);
  318.       close(gcb);
  319.       if getname and not lockname then              { get users name }
  320.         begin
  321.           move(gcbuffer[nameoff],username[1],namesize);
  322.           username[0] := chr(namesize);
  323.           if Pos(#0,username) > 0 then username[0] := chr(Pos(#0,username) - 1)
  324.           else while username[length(username)] = ' ' do Dec(username[0]);
  325.           usename := true
  326.         end
  327.       else usename := false;
  328.       if getime then               { get users time remaining }
  329.         begin
  330.           if ismins then move(gcbuffer[timeoff],timeleft,sizeof(word))
  331.           else move(gcbuffer[timeoff],timetemp,sizeof(real));
  332.           if not ismins then timeleft := trunc(timetemp/60.0);
  333.           if timeleft < 10 then timeleft := 8 else Dec(timeleft,2);
  334.           usetime := true;
  335.           if timedone then timeleft := Min(timeleft,minmax - 2);
  336.           timeleft := Min(timeleft,50);
  337.           GetTime(hour,minute,second,hunsec)
  338.         end
  339.       else usetime := false;
  340.       if getlines then             { get users screen size }
  341.         begin
  342.           move(gcbuffer[lineoff],pagelength,1);
  343.           if doextra = 1 then Inc(pagelength,2);
  344.           if pagelength > 24 then Dec(pagelength)
  345.         end;
  346.       if not (lockcomm or locklocal or lockIRQ) then
  347.         begin                      { get communications port }
  348.           if doextra = 1 then
  349.             begin
  350.               if (gcbuffer[localkey] or gcbuffer[localkey]) = 0 then setlocal := true
  351.               else
  352.                 begin
  353.                   dolocal := false;
  354.                   if gcbuffer[commoff] in [1,3] then IRQnum := 3;
  355.                   portnum := gcbuffer[commoff];
  356.                 end
  357.             end
  358.           else case char(gcbuffer[commoff]) of
  359.               #0,'0','L' : setlocal := true;
  360.               '1'..'4',#1..#4 :
  361.                 begin
  362.                   dolocal := false;
  363.                   if char(gcbuffer[commoff]) in [#2,#4,'2','4'] then IRQnum := 3;
  364.                   if gcbuffer[commoff] in [1..4] then portnum := gcbuffer[commoff] - 1
  365.                   else portnum := gcbuffer[commoff] - ord('1')
  366.                 end
  367.             end
  368.         end;
  369.       case doextra of
  370.           1 : DoOpus114
  371.         end
  372.     end;  {* GetCommand,ProcessFile *}
  373.  
  374.   Procedure DoPCBoard12(filestr : pathstr);
  375.   { Process drop file from PCBoard 12.x and Auntie BBS }
  376.     var
  377.       pctime : real;
  378.       pcmask : array [1..6] of byte absolute pctime;
  379.  
  380.     { PC Board times are in seconds stored as 4 byte reals (QBasic I think)
  381.       they must be converted into Turbo Pascal 6 byte reals, before being
  382.       converted into longint. }
  383.  
  384.     begin {* GetCommand,DoPCBoard12 *}
  385.       if filedone then ShowError(7,'') else filedone := true;
  386.       if length(gcstr) > 2 then
  387.         begin
  388.           delete(gcstr,1,2);
  389.           if gcstr[1] = ':' then delete(gcstr,1,1);
  390.           if not (gcstr[length(gcstr)] in [':','\']) then gcstr := gcstr + '\';
  391.           filestr := gcstr + filestr;
  392.           if not Valid(filestr) then ShowError(9,gcstr)
  393.         end;
  394.       if not Exist(filestr) then ShowError(4,filestr);
  395.       assign(gcb,filestr);
  396.       reset(gcb,1);
  397.       blockread(gcb,gcbuffer,filesize(gcb),insize);
  398.       close(gcb);
  399.       move(gcbuffer[14],username[1],25);
  400.       username[0] := chr(25);
  401.       if Pos(#0,username) > 1 then username[0] := chr(Pos(#0,username) - 1)
  402.       else while username[length(username)] = ' ' do Dec(username[0]);
  403.       usename := true;
  404. { convert stored real format to Turbo Pascal real format }
  405.       pcmask[1] := gcbuffer[79];
  406.       pcmask[2] := $00;
  407.       pcmask[3] := $00;
  408.       pcmask[4] := gcbuffer[76];
  409.       pcmask[5] := gcbuffer[77];
  410.       pcmask[6] := gcbuffer[78];
  411.  
  412.       timeleft := trunc(pctime/60.0); { covert real seconds to word minutes }
  413.       if timeleft < 10 then timeleft := 8 else Dec(timeleft,2);
  414.       usetime := true;
  415.       if timedone then timeleft := Min(timeleft,minmax - 2);
  416.       timeleft := Min(timeleft,50);
  417.       GetTime(hour,minute,second,hunsec);
  418.       if not (lockcomm or locklocal or lockIRQ) then
  419.           if gcbuffer[10] = ord('L') then setlocal := true
  420.     end;  {* GetCommand,DoPCBoard12 *}
  421.  
  422.   Procedure DOSEARCHLIGHT;
  423.     { get path to the door directory from command line }
  424.     var
  425.       sldir  : dirstr;
  426.       slname : namestr;
  427.       slext  : extstr;
  428.  
  429.     begin {* GetCommand,DoSearchLight *}
  430.       if filedone then ShowError(7,'') else filedone := true;
  431.       FSplit(paramstr(0),sldir,slname,slext);
  432.       gamepath := sldir
  433.     end;  {* GetCommand,DoSearchLight *}
  434.  
  435.   Procedure GETCOMPORT;
  436.   { set communications port by command line directive }
  437.     begin {* GetCommand,GetComPort *}
  438.       lockcomm := true;
  439.       if locklocal then ShowError(16,'');
  440.       dolocal := false;
  441.       if (gcstr[length(gcstr)] in ['1'..'4']) then portnum := ord(gcstr[length(gcstr)]) - ord('1')
  442.       else ShowError(13,'')
  443.     end;  {* GetCommand,GetComPort *}
  444.  
  445.   Procedure GETIRQINFO;
  446.   { set IRQ and port information by command line directive }
  447.     var
  448.       IRQerror : word;
  449.  
  450.     begin {* GetIRQInfo *}
  451.       lockIRQ := true;
  452.       if locklocal then ShowError(16,'');
  453.       dolocal := false;
  454.       delete(gcstr,1,1);
  455.       if gcstr[1] = ':' then delete(gcstr,1,1);
  456.       if upcase(gcstr[1]) in ['0'..'9','A'..'F'] then
  457.         begin
  458.           IRQnum  := ord(gcstr[1]) and 15;
  459.           if upcase(gcstr[1]) in ['A'..'F'] then Inc(IRQnum,9);
  460.           portint := IRQarray[IRQnum];
  461.           initval := initarray[IRQnum];
  462.           delete(gcstr,1,1);
  463.           if gcstr[1] = ':' then delete(gcstr,1,1) else ShowError(17,'')
  464.         end
  465.       else ShowError(17,'');
  466.       if length(gcstr) <> 4 then ShowError(17,'');
  467.       Val('$'+gcstr,portadd,IRQerror);
  468.       if IRQerror > 0 then ShowError(18,gcstr)
  469.     end;  {* GetIRQInfo *}
  470.  
  471.   Procedure GETHOFLIM;
  472.   { limit player Hall of Fame appearances }
  473.     var
  474.       error : word;
  475.  
  476.     begin {* GetCommand,GetHofLim *}
  477.       if length(gcstr) < 3 then ShowError(2,'');
  478.       delete(gcstr,1,2);
  479.       if gcstr[1] = ':' then delete(gcstr,1,1);
  480.       Val(gcstr,hoflim,error);
  481.       if error > 0 then ShowError(11,'');
  482.       if not (hoflim in [1..19]) then ShowError(12,'')
  483.     end;  {* GetCommand,GetHofLim *}
  484.  
  485.   Procedure GETHOF;
  486.   { redirect text Hall of Fame output }
  487.     begin {* GetCommand,GetTimeLimit *}
  488.       hofdone := true;
  489.       if length(gcstr) < 3 then ShowError(2,'');
  490.       delete(gcstr,1,2);
  491.       if gcstr[1] = ':' then delete(gcstr,1,1);
  492.       if (pos('.',gcstr) = 0) then
  493.         begin
  494.           if (gcstr[length(gcstr)] in [':','\']) then
  495.               gcstr := gcstr + inhof
  496.           else gcstr := gcstr + '\' + inhof
  497.         end;
  498.       if not Valid(gcstr) then ShowError(8,'')
  499.       else texthof := gcstr
  500.     end;  {* GetCommand,GetTimeLimit *}
  501.  
  502.   Procedure GETTIMELIMIT;
  503.   { set maximum time limit }
  504.     begin {* GetCommand,GetTimeLimit *}
  505.       timedone := true;
  506.       if length(gcstr) < 3 then ShowError(2,'');
  507.       delete(gcstr,1,2);
  508.       if gcstr[1] = ':' then delete(gcstr,1,1);
  509.       val(gcstr,minmax,dummy);
  510.       if dummy <> 0 then ShowError(8,'');
  511.       if filedone then timeleft := Min(timeleft,minmax - 2)
  512.       else
  513.         begin
  514.           usetime := true;
  515.           timeleft := Min(minmax - 2,50);
  516.           GetTime(hour,minute,second,hunsec)
  517.         end
  518.     end;  {* GetCommand,GetTimeLimit *}
  519.  
  520.   Procedure DOPORTS;
  521.   { use default IRQ and port information for communications }
  522.     begin {* GetCommand,DoPorts *}
  523.       portadd := portarray[portnum];
  524.       portint := IRQarray[irqnum];
  525.       initval := initarray[irqnum]
  526.     end;  {* GetCommand,DoPorts *}
  527.  
  528.   Procedure GETAGAIN;
  529.   { get multiple play parameters }
  530.     var
  531.       error : word;
  532.  
  533.     begin {* GetCommand,GetAgain *}
  534.       doagain := true;
  535.       delete(gcstr,1,2);
  536.       if gcstr[1] = ':' then delete(gcstr,1,1);
  537.       If length(gcstr) > 0 then
  538.         begin
  539.           Val(gcstr,againtime,error);
  540.           if error > 0 then ShowError(19,'');
  541.           if againtime < 5 then ShowError(20,'')
  542.         end
  543.       else againtime := 10
  544.     end;  {* GetCommand,GetAgain *}
  545.  
  546.   Procedure GETNAME;
  547.     var
  548.       gloop : byte;
  549.  
  550.     begin {* GetCommand,GetName *}
  551.       delete(gcstr,1,2);
  552.       if gcstr[1] = ':' then delete(gcstr,1,1);
  553.       if length(gcstr) > 0 then
  554.         begin
  555.           lockname := true;
  556.           usename := true;
  557.           username := gcstr;
  558.           for gloop := 1 to length(username) do if username[gloop] = '_' then
  559.               username[gloop] := ' '
  560.         end
  561.     end;  {* GetCommand,GetName *}
  562.  
  563. { slash '/' switches }
  564. {    active switches :  12 4567 9ABCD F HI KLMNOPQRST VWXYZ }
  565. {  reserved switches : 0  3    8       G             U      }
  566. { available switches :               E    J                 }
  567. {   program switches : +-][=. }
  568.  
  569. { dash '-' switches } { unused at this point }
  570. {    active switches :                                      }
  571. {  reserved switches :                                      }
  572. { available switches : 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ }
  573.  
  574.  
  575.   begin {* GetCommand *}
  576.     usetime  := false;       { default - no time limit }
  577.     usename  := false;       { default - no user name }
  578.     usereal  := false;       { default - only know alias }
  579.     pagelength := 24;        { default - 24 line screen }
  580.     timexp   := false;       { set time to not expired }
  581.     if paramcount > 7 then ShowError(1,'');
  582.     for gloop := 1 to paramcount do
  583.       begin
  584.         gcstr := paramstr(gloop);
  585.         if (gcstr[1] <> '/') or (length(gcstr) < 2) then ShowError(2,'');
  586.         case upcase(gcstr[2]) of
  587. {PCBoard12x}'1' : DoPCBoard12('PCBoard.Sys');
  588. {2 A.M.}    '2' : ProcessText('Jumper.Dat',  true,true,false,true,  5, 8, 0, 9,4,4);
  589. {Opus 1.13} '3' : ShowError(3,'Opus-CBCS 1.13 ');
  590. {WWIV,TG}   '4' : ProcessText('Chain.Txt',   true,true,true, false, 2,16,10,21,1,2);
  591. {RyBBS}     '5' : ProcessText('CurrUser.BBS',true,true,false,true,  1,13, 0, 6,1,0);
  592. {Spitfire}  '6' : ProcessText('SFDoors.Dat', true,true,false,true,  2, 7, 0, 6,1,6);
  593. {Auntie}    '7' : DoPCBoard12('Auntie.Sys');
  594. {Sapphire}  '8' : ShowError(3,'Sapphire BBS ');
  595. {SeachLight}'9' : DoSearchLight;
  596. {XBBS}      '0' : ShowError(3,'XBBS ');
  597. {DrWy,GT}   'D' : ProcessText('Door.Sys',    true,true,false,true,  1, 4, 0, 2,1,0);
  598. {Forum}     'F' : ProcessText('UserInfo.Txt',true,true,false,false, 1, 4, 0, 5,1,0);
  599. {Genesis}   'G' : ShowError(3,'Genesis ');
  600. {Phoenix}   'H' : ProcessText('Info.Txt',    true,true,false,true,  1, 7, 0, 3,1,5);
  601. {ModuleX}   'M' : ProcessText('Number.Txt',  true,true,false,false, 1, 4, 0, 5,1,0);
  602. {PCBoard14x}'P' : ProcessFile('PCBoard.Sys', true,true,false,true ,84,25,61, 0,125,18,0);
  603. {GAP,Force} 'S' : ProcessText('Door.Sys',    true,true,true, true, 10,19,21, 1,4,0);
  604. {UBBS}      'U' : ShowError(3,'UBBS ');
  605. {WildCat}   'W' : ProcessText('CallInfo.BBS',true,true,true, true,  1, 5,23,29,4,3);
  606. {Opus 1.14} 'O' :
  607.               begin
  608.                 if (length(gcstr) > 3) and (upcase(gcstr[3]) in ['0'..'9','A'..'F'])
  609.                     and (upcase(gcstr[4]) in ['0'..'9','A'..'F']) then
  610.                   begin
  611.                     opchs := Copy(gcstr,3,2);
  612.                     delete(gcstr,3,2);
  613.                     ProcessFile('LastUS'+opchs+'.Dat',true,true,true,true,104,32,1030,173,1026,1024,1)
  614.                   end
  615.                 else ProcessFile('LastUser.Dat',true,true,true,true,104,32,1030,173,1026,1024,1)
  616.               end;
  617. {EIS-PC}    'R' :
  618. {FoReM}       begin  { Get node number }
  619. {OLEcom}        if (length(gcstr) > 2) and (gcstr[3] in ['0'..'9']) then
  620. {QuickBBS}        begin
  621. {RBBS}              inchar := gcstr[3];
  622. {Remote Access}     delete(gcstr,3,1);
  623. {TAG}               ProcessText('DorInfo'+inchar+'.Def',true,true,false,true,7,12,0,4,4,1)
  624. {TP-Board}        end
  625.                 else ProcessText('DoorInfo.Def',true,true,false,true,7,12,0,4,4,1)
  626.               end;
  627.  
  628. {Local}     'L' : if locklocal then ShowError(7,'') else locklocal := true;
  629. {lockcomm}  'C' : if lockcomm or lockIRQ then ShowError(7,'')
  630.                 else if not setlocal then GetComPort;
  631. {lockIRQ}   'I' : if lockcomm or lockIRQ then ShowError(7,'')
  632.                 else if not setlocal then GetIRQInfo;
  633.  
  634. {doagain}   'A' : if doagain then ShowError(7,'') else GetAgain;
  635. {baudlock}  'B' : if baudlock then ShowError(7,'') else baudlock := true;
  636. {getname}   'N' : if lockname then ShowError(7,'') else GetName;
  637. {checkcd}   'K' : if not checkcd then ShowError(7,'') else checkcd := false;
  638. {doquiet}   'Q' : if doquiet then ShowError(7,'') else doquiet := true;
  639. {hoflim}    'X' : if hoflim < 20 then ShowError(7,'') else GetHofLim;
  640. {hofpath}   'Y' : if hofdone then ShowError(7,'') else GetHOF;
  641. {timelimit} 'Z' : if timedone then ShowError(7,'') else GetTimeLimit
  642.             else if gcstr[1] in programset then  { program defined symbols }
  643.               begin
  644.                 case gcstr[1] of
  645.                     '+' : if plusindex = 0 then plusindex := gloop else ShowError(7,'');
  646.                     '-' : if minusindex = 0 then plusindex := gloop else ShowError(7,'');
  647.                     ']' : if closeindex = 0 then plusindex := gloop else ShowError(7,'');
  648.                     '[' : if openindex = 0 then plusindex := gloop else ShowError(7,'');
  649.                     '=' : if equalindex = 0 then plusindex := gloop else ShowError(7,'');
  650.                     '.' : if dotindex = 0 then plusindex := gloop else ShowError(7,'')
  651.                   end
  652.               end
  653.             else ShowError(2,'')
  654.           end
  655.       end;
  656.     if locklocal and (lockcomm or lockIRQ) then ShowError(16,'');
  657.     if locklocal or setlocal then dolocal := true;
  658.     doecho := not dolocal;
  659.     if not (dolocal or lockIRQ) then DoPorts;
  660.     if not hofdone then texthof := gamepath + inhof
  661.   end;  {* GetCommand *}
  662.  
  663. end. Unit
  664.  
  665.  
  666. Text Data Files
  667.   BBS System      SynData File    type   Name  Real  Time  Line  Comm  Local
  668. x 2 A.M. BBS         Jumper.Dat   text    5+6    3     8m  ----   9,4  ----
  669. x DoorWay          2 Door.Sys     text      1  ----    4m  ----   2,1  ----
  670. x EIS-PC           3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  671. x Force BBS        1 Door.Sys     text     10  ----   19m   21    1,4  ----
  672. x FoReM            3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  673. x Forum            4 UserInfo.Txt text      1  ----    4s  ----   5,1   5,L
  674. x GAP              1 Door.Sys     text     10  ----   19m   21    1,4  ----
  675.   Genesis            CallInfo.BBS text      1  ----    5m   23    ???  28,L
  676. x GT               2 Door.Sys     text      1  ----    4m  ----   2,1  ----
  677. x ModuleX          4 Number.Txt   text      1  ----    4s  ----   5,1   5,L
  678. x OLEcom           3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  679. x Phoenix            Info.BBS     text      1  ----    7m  ----   3,1   2,L
  680. x Quick BBS        3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  681. x RBBS             3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  682. x Remote Acces     3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  683. x RyBBS              CurrUser.BBS text      1  ----   13m  ----   6,1  ----
  684. x Spitfire BBS       SFDoors.Dat  text      2  ----    7m  ----   6,1  ----
  685. x TAG              3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  686. x TP-Board         3 DorInfo#.Def text    7+8  ----   12m  ----   4,4  ----
  687. x WildCat            CallInfo.BBS text      1  ----    5m   23   29,4  28,L
  688. x WWIV               Chain.Txt    text      2    3    16s   10   21,1  15,0
  689. x Telegard         x Can emulate most of the above
  690.  
  691. Binary Data Files
  692.   BBS System      SynData File    type   Name  Real  Time  Line  Comm  Local
  693. - Auntie BBS       5 Auntie.Sys   b128   14n25 ----   76c  ----  ----  10,L
  694.   OPUS-CBCS 1.13     LastUser.BBS b128    0l   ----   ???  123   ????  ????
  695. - OPUS-CBCS 1.14     LastUsXX.Dat b     104n32 0n36 1030mw 173  1026w  ----
  696. - PCBoard 12.x     5 PCBoard.Sys  b128   14n25 ----   76c  ----  ----  10,L
  697. x PCBoard 14.x       PCBoard.Sys  b128   84n25 ----   61mw ----  125c  18,L
  698.   Sapphire BBS       Sapphire.Dat b545    0l   ----   ???   87   ????  ????
  699.  
  700. Command Line Driven
  701. x Search Light BBS
  702.  
  703. Unknown Data Files
  704.   UBBS
  705.   XBBS
  706.  
  707. x in use
  708. - beta stage
  709.  
  710. m minutes
  711. s seconds
  712.  
  713. r real
  714. i integer
  715. w word
  716. c char
  717.  
  718.  
  719. 2 A.M., Auntie BBS, DoorWay, EIS-PC, Force BBS, FoReM, Forum, GAP, GT,
  720. ModuleX, OLEcom, Opus-CBCS 1.14, PCBoard 12.x, PCBoard 14.x, Phoenix,
  721. Quick BBS, RBBS, Remote Access, RyBBS, SearchLight BBS, Spitfire BBS,
  722. TAG, Telegard, TP-Board, WildCat, WWIV.
  723. /* */
  724. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  725. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  726. /*%                                                                       %*/
  727. /*%                     U S E R   D A T A B A S E                         %*/
  728. /*%                                                                       %*/
  729. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  730. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  731. /*                                                                         */
  732. /* The user data base consists of two files: a data file (USER.DAT) and a  */
  733. /* matching index file (USER.IDX).  The data file is a direct access file  */
  734. /* with fixed length, 1 kb records, one for each user.  The index contains */
  735. /* one computed, 4-byte CRC value for each user name.                      */
  736. /*                                                                         */
  737. /* Access to the user database can be done sequentially on the main data   */
  738. /* file or by keyed access by computing the special CRC value of the       */
  739. /* desired user name, looking up that value in the index file, and then    */
  740. /* by seeking the positionally correspondent record in the main file.      */
  741. /*                                                                         */
  742. /* WARNING:                                                                */
  743. /*                                                                         */
  744. /* Any changes made to user names or the number, or order, of user records */
  745. /* will put the index into an unsynchronized state that may result in      */
  746. /* undefined and potentially dangerous problems unless the index is        */
  747. /* updated or rebuilt by the utility.  One way of doing this is to run     */
  748. /* the oIndex program after such changes to properly rebuild the index.    */
  749. /*                                                                         */
  750. /* WARNING:                                                                */
  751. /*                                                                         */
  752. /* Any changes to a user record made by an external utility that is        */
  753. /* operating independently in another partition or work-station while      */
  754. /* that user is online will be overwritten when Opus updates the user      */
  755. /* record with its own working copy of it.                                 */
  756. /*                                                                         */
  757. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  758. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  759.  
  760.  
  761.    #define MAXLREAD 0x100  /* Number of msg area pointers to maintain      */
  762.  
  763.    struct   _usr
  764.    {
  765. n   0  35      char name[36];       /* Caller's first and last names                */
  766.    36  71      char city[36];       /* Caller's location                            */
  767.    72  87      char pwd[16];        /* Password                                     */
  768.    88 103      char usrtel[16];     /* User Tel# for ref or future callback         */
  769. a 104 135      char alias[32];      /* User alias if ID is not it                   */
  770.   136 137      word times;          /* Number of previous calls to this system      */
  771.   138          byte ClassPriv;      /* User Access Privilege                        */
  772.   139          byte help;           /* Help level (see below)                       */
  773.   140          byte tabs;           /* 0=transmit <sp> instead of <tab>             */
  774.   141          byte language;       /* Lang set no. (1-6) as defined in .PRM file.  */
  775.   142 143      word nulls;          /* Number of Nulls (delays) after <cr>          */
  776.   144 145      word msg;            /* Last message area accessed                   */
  777.   146 147      word Bits;           /* User option flags (See Below)                */
  778.  
  779.       /* Each of the 32 bits within the following 4-byte (long) item       */
  780.       /* represents a single user 'key'.   To have access to any Opus      */
  781.       /* function that has any of 32 'lock' bits set for it, there has to  */
  782.       /* be at least the matching key bits set in this item.  Having other */
  783.       /* key bits sit does not matter.                                     */
  784.       /*                                                                   */
  785.       /* For maintenance and discussion, key and lock bits are referred to */
  786.       /* by the characters A-Z and 0-5 where 'A' is bit 0 (least           */
  787.       /* significant) and '5' refers to bit 31 (most significant).         */
  788.  
  789.   148 151      long ClassLock;      /* 32 User 'Keys'                               */
  790.                            /* Each bit of this long object corresponds to  */
  791.                            /* each of 32 possible user 'keys' which are    */
  792.                            /* referred to by the character (A-Z,0-5) where */
  793.                            /* the least significant) bit is called 'A' and */
  794.                            /* the most significant nit is called '5'.      */
  795.  
  796.   152 155      long ludate;         /* Date of user's Last Call to system expressed */
  797.                            /* as seconds since 01-Jan-70 in GMT/UTC time.  */
  798.  
  799.   156 157      int  time;           /* Time on-line so-far today                    */
  800.  
  801.   158 159      word flag;           /* User file management flags (see below)       */
  802.  
  803.   160 163      long upld;           /* Total kilobytes uploaded to date.            */
  804.   164 167      long dnld;           /* Total kilobytes downloaded to date.          */
  805.   168 171      int  dnldl;          /* Total kilobytes downloaded last/current call */
  806.   172 173      word files;          /* Last file area accessed                      */
  807. x 174          byte width;          /* Width of the caller's monitor                */
  808. y 175          byte len;            /* Height of the caller's                       */
  809.   176 177      word credit;         /* FidoNet usage credit in cents                */
  810.   178 179      word debit;          /* FidoNet usage in cents                       */
  811.  
  812.   180 187      char spcoec[8];      /* Special OECC to show after logon             */
  813.                            /* Good for clubs, stores, user groups          */
  814.                            /* Eg, "Welcome to the dBase User Group"        */
  815.  
  816.   188 192      byte saccnt[5];      /* Array of 5 counters which correspond to the  */
  817.                            /* files SPANN#.BBS which reside on the path    */
  818.                            /* given by 'spcldir' in the .PRM file. If any  */
  819.                            /* is > 0 than the user is shown the matching   */
  820.                            /* announcement and is decremented.  When 0, it */
  821.                            /* is no longer displayed.                      */
  822.  
  823.   193          byte exflag;         /* Expiration behavior flags (see below)        */
  824.  
  825.   194 197      long xdate;          /* Expiry date always rounded to (0000 hrs) and */
  826.                            /* as secs since 01-Jan-70 in *LOCAL* time for  */
  827.                            /* reasons of cross-zone accounting equivelnce. */
  828.  
  829.   198 202      long crmin;          /* Total minutes given to user                  */
  830.   203 206      long dbmin;          /* Total minutes used  by user                  */
  831.  
  832.   207 238      char ulikes[32];     /* Reserved for future feature                  */
  833.   239 242      long fudate;         /* First Call Date(secs since 01-Jan-70 UTC/GMT)*/
  834.  
  835.   243 258      byte reserved[16];   /* Filler, reserved.                            */
  836.  
  837.       /* The following item contains for each of the 256 possible areas,   */
  838.       /* the last message number that the user read in that area.  A value */
  839.       /* of zero means the area was not accessed by the user yet.          */
  840.  
  841.   259 260      word lastmsg[MAXLREAD];
  842.  
  843.  
  844.   261 264      long OPUS_id;           /* Opus Record ID ... Must always be 'OPUS'  */
  845.  
  846.  
  847.       /* The next 7 sets of 'id' and 'inf' data are for external utilities */
  848.       /* that have been registered with OpusInfo to use for the storage    */
  849.       /* and independent maintenance of auxiliary information.  The first  */
  850.       /* (long) array of 7 items holds the registered ID's of utilities    */
  851.       /* that make use of the 7 matching 32-byte data blocks that follow.  */
  852.       /*                                                                   */
  853.       /* Any utility may make use of any of the 7 data blocks providing    */
  854.       /* they ensure that the desired blocks are not already used as would */
  855.       /* be indicated by an ID in the matching ID positions.  If free,     */
  856.       /* then the utility claims them by writing its registered ID in the  */
  857.       /* matching ID positions.  It is up to the utility to ensure that    */
  858.       /* enough positions are free in all of the user records that would   */
  859.       /* potentially be accessed by it.                                    */
  860.       /*                                                                   */
  861.       /* Currently registered ID's ........................................*/
  862.       /*                                                                   */
  863.       /* 0x57555646 .. FVIEW ... File viewing utility by Doug Boone        */
  864.       /* 0x4F4D414E .. OMAN  ... Opus system manager by Tom Kashuba        */
  865.  
  866.  
  867.   265 271      long extern_id[7];      /* LONG ID number for external programs      */
  868.                               /* Must be registered with OpusInfo          */
  869.  
  870.   272 495      byte extern_inf[7][32]; /* 7 32-byte external util data blocks       */
  871.                            224
  872.    };
  873.  
  874.  
  875. /*-------------------------------------------------------------------------*/
  876. /* 'Bits' -- User Option Flag Meanings                                     */
  877. /*-------------------------------------------------------------------------*/
  878.  
  879.    #define  NO_IBMCHAR  0x0004 /* Cannot receive IBM textmode graphics     */
  880.    #define  USE_LORE    0x0008 /* Wants LORE editor instead of OPed        */
  881.    #define  MORE_PROMPT 0x0010 /* Wants the page break "MORE?" question    */
  882.    #define  ANSI        0x0020 /* Can handle ANSI video                    */
  883.    #define  CONFIG_SET  0x0040 /* OPUS logon questions answered            */
  884.    #define  FORMFEED    0x0080 /* SET=xmit clearscreen, CLEAR=eat formfeed */
  885.    #define  AVATAR      0x0100 /* Can handle AVATAR (aka "oANSI") video    */
  886.  
  887.    #define  USE_PHONE   0x0400 /* User Modem Tel# to Call Back    (future) */
  888.    #define  USE_ALIAS   0x0800 /* Use ALIAS in var user functions (future) */
  889.  
  890.    #define  NO_NAME     0x1000 /* Don't List User's Name in User List      */
  891.    #define  NO_TIME     0x2000 /* Don't List User's Last-On in User List   */
  892.    #define  NO_CITY     0x4000 /* Don't List User's City in User List      */
  893.  
  894.    #define  CURSOR_CONTROL (ANSI|AVATAR)
  895.  
  896.  
  897. /*-------------------------------------------------------------------------*/
  898. /* 'flag' -- User file management flags                                    */
  899. /*                                                                         */
  900. /* These flags are used by the user file manager within oMan to control    */
  901. /* the reuse and deletion of user records.  External utilities may use     */
  902. /* then as long as they folow the conventions established by oMan.         */
  903. /*                                                                         */
  904. /*-------------------------------------------------------------------------*/
  905.  
  906.    #define REUSE       0x0001    /* Re-use rec for next new caller         */
  907.    #define PURGE       0x0002    /* Remove record in next OMAN Pack        */
  908.                                  /* All other bits currently reserved      */
  909.  
  910. /* The following value is used as a mask to cover all of the 8 separate    */
  911. /* bit values in range 0x0100-0x8000.  They each represent a 'group tag'   */
  912. /* as implemented in the Opus user manager, oMan, and are referred to by   */
  913. /* the letters 'A' (0x0100) through 'H' (0x8000).  Group tags are benign   */
  914. /* markers that are for the covenience of user record maintenance and are  */
  915. /* used by the user manager only.                                          */
  916.  
  917.    #define GRPTAGS     0xFF00
  918.  
  919.  
  920. /*-------------------------------------------------------------------------*/
  921. /* 'help' -- User help levels (menu style)                                 */
  922. /*-------------------------------------------------------------------------*/
  923.  
  924.    #define TOTMDL         4      /* Total menu detail levels               */
  925.  
  926.    #define HITECH      0x00      /* 1-line, top-of-screen, bar-style menus */
  927.    #define EXPERT      0x02      /* No text at all, just a prompt          */
  928.    #define REGULAR     0x04      /* Lists menu option letters only.        */
  929.    #define NOVICE      0x06      /* Full menu command titles listed.       */
  930.  
  931. /* #define USING_FTB   0xFF */   /* Old mode.  Not supported in 1.10.      */
  932.  
  933.  
  934. /*-------------------------------------------------------------------------*/
  935. /*  'exflag' -- Flags dealing with user expiration control                 */
  936. /*-------------------------------------------------------------------------*/
  937. /* These definitions are the bit values of the 'exflag' flags item which   */
  938. /* determine the type and handling of user expiration.  The values of      */
  939. /* ExpByDate and ExpByDate set the type of expiration, if any.  The values */
  940. /* of ExpDemote and ExpAxe determine how to handle expired users.          */
  941. /*-------------------------------------------------------------------------*/
  942.  
  943.    #define EXPBYDATE   0x01  /* Expire user by date.  That is, consider    */
  944.                              /* them as expired when they log on AFTER the */
  945.                              /* date stored in 'xdate'.                    */
  946.  
  947.    #define EXPBYMINS   0x02  /* Expire user by minutes of usage.  That is, */
  948.                              /* consider them as expired when the minutes  */
  949.                              /* they have used thus far (crmin) exceeds    */
  950.                              /* the minutes they were alotted (dbmin).     */
  951.  
  952.    #define EXPDEMOTE   0x10  /* If user is expired, reduce their privilege */
  953.                              /* to TWIT or, if set, to the demote value    */
  954.                              /* set in the PRM file.                       */
  955.  
  956.    #define EXPAXE      0x20  /* If user is expired, disconnect them.       */
  957.  
  958.  
  959.  
  960.  
  961.  
  962.  
  963. /* */
  964. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  965. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  966. /*%                                                                       %*/
  967. /*%                  L A S T   U S E R   R E C O R D                      %*/
  968. /*%                                                                       %*/
  969. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  970. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  971. /*%                                                                       %*/
  972. /*%  The "LASTUSER" record is a single record file that is written to     %*/
  973. /*%  disk after a user logs off and just prior to every time that Opus    %*/
  974. /*%  does an external exit.  The file contains a copy of the user's       %*/
  975. /*%  record (in its entirety) along with an extended data block that      %*/
  976. /*%  contains additional environmental information that is useful to      %*/
  977. /*%  external programs.                                                   %*/
  978. /*%                                                                       %*/
  979. /*%  An option in the PRM file optionally allows the user record portion  %*/
  980. /*%  of the file to read back into Opus, overlaying the live copy in      %*/
  981. /*%  memory.  This is extremely powerful and DANGEROUS in that the user's %*/
  982. /*%  profile can be updated (or damaged) dynamically!                     %*/
  983. /*%                                                                       %*/
  984. /*%  The last user file name is formatted as LASTUS##.DAT where '##'      %*/
  985. /*%  is the task number (expressed as hexadecimal) of the running Opus.   %*/
  986. /*%  The task number, being one of several arguments passed to the        %*/
  987. /*%  program, allows it to properly compose the LASTUSER file name so it  %*/
  988. /*%  can open and process it.  Once accessed, all of its data is          %*/
  989. /*%  available for use by the program.                                    %*/
  990. /*%                                                                       %*/
  991. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  992. /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
  993.  
  994.    struct _lu_file
  995.    {
  996.     0 495      struct _usr user;    /* Copy of user record                          */
  997.   496 497      word   baud;         /* Current user's baud (0 == keyboard!)         */
  998. c 498 499      word   port;         /* Current port #                               */
  999.   500 501      word   task;         /* Active task number                           */
  1000. m 502 503      word   mins;         /* User's minutes remaining                     */
  1001.   504 505      word   msgarea;      /* Which message area user is in                */
  1002.   506 507      word   filearea;     /* Which file area user is in                   */
  1003.  
  1004.   508 511      long   timeoff;      /* Date/Time that caller's session must end by. */
  1005.                            /* As secs since 01-Jan-70 UTC/GMT              */
  1006.  
  1007.       struct tm tmoff;     /* MS-C 'tm' struct of above but as local time  */
  1008.  
  1009.       char   laston[25];   /* Orig Last Call Date as ASCIIZ string because */
  1010.                            /* same field in user rec is curr logon time    */
  1011.    };
  1012.  
  1013.  
  1014.  
  1015. alias          104..135 /0
  1016. a 104 135      char alias[32];      /* User alias if ID is not it                   */
  1017. name             0.. 35 /0
  1018. n   0  35      char name[36];       /* Caller's first and last names                */
  1019. time (minutes) 502..503 word minutes
  1020. m 502 503      word   mins;         /* User's minutes remaining                     */
  1021. lines          175      byte
  1022. y 175          byte len;            /* Height of the caller's                       */
  1023. comm           498..499 word ?????
  1024. c 498 499      word   port;         /* Current port #                               */
  1025.